package org.go.scheduler.database;

import org.go.domain.GoDomain;
import org.go.domain.IntervalUnit;
import org.go.scheduler.ScheduleBuilder;
import org.go.trigger.Trigger;
import org.go.trigger.TriggerBuilder;

public class CalendarIntervalScheduleBuilder {

	/**
	 * Create a CalendarIntervalScheduleBuilder.
	 * 
	 * @return the new CalendarIntervalScheduleBuilder
	 */
	public static CalendarIntervalScheduleBuilder calendarIntervalSchedule() {
		return new CalendarIntervalScheduleBuilder();
	}

	private int interval = 1;

	private IntervalUnit intervalUnit = IntervalUnit.DAY;

	private int misfireInstruction = GoDomain.MISFIRE_INSTRUCTION_SMART_POLICY;

	private CalendarIntervalScheduleBuilder() {
	}

	private void validateInterval(int interval) {
		if (interval <= 0)
			throw new IllegalArgumentException("Interval must be a positive value.");
	}

	/**
	 * Build the actual Trigger -- NOT intended to be invoked by end users,
	 * but will rather be invoked by a TriggerBuilder which this 
	 * ScheduleBuilder is given to.
	 * 
	 * @see TriggerBuilder#withSchedule(ScheduleBuilder)
	 */
	public Trigger build() {
		Trigger st = null;
		/*
		new RepeatTrigger();
		st.setRepeatInterval(interval);
		st.setRepeatIntervalUnit(intervalUnit);
		st.setMisfireInstruction(misfireInstruction);
		*/
		return st;
	}

	/**
	 * Specify the time unit and interval for the Trigger to be produced.
	 * 
	 * @param interval the interval at which the trigger should repeat.
	 * @param unit  the time unit (IntervalUnit) of the interval.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withInterval(int interval, IntervalUnit unit) {
		if (unit == null)
			throw new IllegalArgumentException("TimeUnit must be specified.");
		validateInterval(interval);
		this.interval = interval;
		this.intervalUnit = unit;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.DAY that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInDays the number of days at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInDays(int intervalInDays) {
		validateInterval(intervalInDays);
		this.interval = intervalInDays;
		this.intervalUnit = IntervalUnit.DAY;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.HOUR that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInHours the number of hours at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInHours(int intervalInHours) {
		validateInterval(intervalInHours);
		this.interval = intervalInHours;
		this.intervalUnit = IntervalUnit.HOUR;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.MINUTE that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInMinutes the number of minutes at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInMinutes(int intervalInMinutes) {
		validateInterval(intervalInMinutes);
		this.interval = intervalInMinutes;
		this.intervalUnit = IntervalUnit.MINUTE;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.MONTH that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInMonths the number of months at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInMonths(int intervalInMonths) {
		validateInterval(intervalInMonths);
		this.interval = intervalInMonths;
		this.intervalUnit = IntervalUnit.MONTH;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.SECOND that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInSeconds the number of seconds at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInSeconds(int intervalInSeconds) {
		validateInterval(intervalInSeconds);
		this.interval = intervalInSeconds;
		this.intervalUnit = IntervalUnit.SECOND;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.WEEK that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInWeeks the number of weeks at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInWeeks(int intervalInWeeks) {
		validateInterval(intervalInWeeks);
		this.interval = intervalInWeeks;
		this.intervalUnit = IntervalUnit.WEEK;
		return this;
	}

	/**
	 * Specify an interval in the IntervalUnit.YEAR that the produced 
	 * Trigger will repeat at.
	 * 
	 * @param intervalInYears the number of years at which the trigger should repeat.
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#getRepeatInterval()
	 * @see CalendarIntervalTrigger#getRepeatIntervalUnit()
	 */
	public CalendarIntervalScheduleBuilder withIntervalInYears(int intervalInYears) {
		validateInterval(intervalInYears);
		this.interval = intervalInYears;
		this.intervalUnit = IntervalUnit.YEAR;
		return this;
	}

	/**
	 * If the Trigger misfires, use the 
	 * {@link CalendarIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING} instruction.
	 * 
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING
	 */
	public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionDoNothing() {
		misfireInstruction = GoDomain.MISFIRE_INSTRUCTION_DO_NOTHING;
		return this;
	}

	/**
	 * If the Trigger misfires, use the 
	 * {@link CalendarIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW} instruction.
	 * 
	 * @return the updated CalendarIntervalScheduleBuilder
	 * @see CalendarIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
	 */
	public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionFireAndProceed() {
		misfireInstruction = GoDomain.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
		return this;
	}

	/**
	 * If the Trigger misfires, use the 
	 * {@link Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY} instruction.
	 * 
	 * @return the updated CronScheduleBuilder
	 * @see Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
	 */
	public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() {
		misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY;
		return this;
	}
}
